home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
oper_sys
/
emerald
/
emrldsys.lha
/
Language
/
Compiler
/
semantics.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-16
|
16KB
|
579 lines
/*
* @(#)semantics.c 1.10 10/24/89
*/
#include "assert.h"
#include "scan.h"
#include "nodes.h"
#include "error.h"
#include "opNames.h"
#include "flags.h"
#include "system.h"
#include "trace.h"
#include "option.h"
#include "builtins.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
#include <sys/file.h>
#include <a.out.h>
#include <errno.h>
#undef NULL
#include "ndbm.h"
#undef NULL
#define NULL 0
extern char *emDirectory, *emdbDirectory;
static struct {
Boolean shouldDo;
int verboseLevel;
char *name;
} treePasses[] = {
TRUE , 1, "parsing",
TRUE , 1, "removing sugar",
TRUE , 1, "processing symbols",
TRUE , 1, "doing imports",
TRUE , 1, "doing manifests",
TRUE , 1, "assigning types",
TRUE , 1, "checking types",
TRUE , 1, "inline detection",
FALSE, 0, "figuring concrete types",
FALSE, 0, "figuring locals",
TRUE , 1, "doing exports",
FALSE, 0, "code generation",
0, 0, 0};
extern void removeSugar(), processSymbols(), doManifest(),
DisplayTree(), assignTypes(), typeCheck(), detectInlines(),
multiPassManifest(), doSymbolGraph(),
doKnowCTs(), doKnowManifests(),
doKnowLocals(), newAssignTypes();
extern char *makeOIDDotoFileName();
char workingDirectory[MAXPATHLEN];
#define MAXDOTSFILES 100
typedef struct sDotsRec {
Boolean alreadyGenerated;
int codeFileNumber;
OID codeOID;
OID createdOID;
} DotsRec, *DotsRecPtr;
DotsRec dotsFiles[MAXDOTSFILES];
static int nextDotsFile = 0;
static void doTree(name, fTreeFile, Root)
char *name;
FILE *fTreeFile;
NodePtr Root;
{
register int stage;
for (stage = 0;
treePasses[stage].name && strcmp(name, treePasses[stage].name);
stage++) ;
assert(treePasses[stage].name != NULL);
if (treePasses[stage].shouldDo) {
if (tflag) {
TRACE0(passes, 1, "Writing the tree file.");
fprintf(fTreeFile, "After %s\n", treePasses[stage].name);
DisplayTree(fTreeFile, Root, treePasses[stage].verboseLevel, 9999);
}
}
}
extern NodePtr readTree();
void doExports(), doImports(), generateCode();
extern int nextObjectNumber;
FILE *treeFile = NULL;
FILE *codeFile = NULL;
char *codeFileName = NULL, *codeFileRoot;
/*
* Call the program named f with the arguments v, and stdin and out
* directed to inf and outf respectively.
*/
#include <sys/wait.h>
int callsys(f, v, inf, outf)
char *f, **v, *inf, *outf;
{
int t;
union wait status;
register char **cpp;
IFTRACE(passes, 5) {
fprintf(stdout, "%s:", f);
for (cpp = v; *cpp != 0; cpp++) fprintf(stdout, " %s", *cpp);
if (inf != NULL) fprintf(stdout, " < %s", inf);
if (outf != NULL) fprintf(stdout, " > %s", outf);
fprintf(stdout, "\n");
}
t = vfork();
if (t == -1) {
fprintf(stderr, "No more processes\n");
return (100);
}
if (t == 0) { /* I am the child */
int infd, outfd;
if (inf != NULL) {
infd = open(inf, O_RDONLY, 0666);
(void) dup2(infd, 0);
}
if (outf != NULL) {
outfd = open(outf, O_WRONLY | O_CREAT | O_TRUNC, 0666);
(void) dup2(outfd, 1);
}
execv(f, v);
fprintf(stderr, "Can't find %s\n", f);
(void) fflush(stderr);
_exit(100);
}
while (t != wait(&status))
;
if ((t=status.w_termsig) != 0 && t!=14) {
if (t!=2) {
fprintf(stderr, "Fatal error in %s\n", f);
}
}
return (status.w_retcode);
}
extern int link(), symlink();
void myLink(existing, new, symbolic, Root)
char *existing, *new;
Boolean symbolic;
NodePtr Root;
{
int (*linkroutine)() = symbolic ? symlink : link;
char *linkroutinename = symbolic ? "symlink" : "link";
if ((*linkroutine)(existing, new) < 0) {
if (errno == EEXIST) {
if (unlink(new) < 0) {
ErrorMessage(Root, "Cannot unlink %s: %s", new,
errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
} else {
if ((*linkroutine)(existing, new) < 0) {
ErrorMessage(Root, "Cannot %s %s to %s: %s", linkroutinename, new,
existing,
errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
}
}
} else {
ErrorMessage(Root, "Cannot %s %s to %s: %s", linkroutinename, new, existing,
errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
}
}
}
static int finishedPass;
#define TOTALPASSES 14
void checkCompletion()
{
if (! Cflag) return;
if (Cvalue <= 0 && TOTALPASSES + Cvalue <= finishedPass) exit(0);
else if (Cvalue > 0 && finishedPass >= Cvalue) exit(0);
}
extern void initializeOwnStuff();
void DoneParsing(Root)
NodePtr Root;
{
char *treeFileName, *p;
char *realDotoFileName, *createdDotoFileName;
char **systemBuffer, **execvec;
char binpath[100];
int systemResult, i;
FILE *dotgFile;
CheckForErrors();
if (!strcmp(currentFileName, "<stdin>")) {
codeFileRoot = malloc(6);
strcpy(codeFileRoot, "stdin");
} else {
for (p = currentFileName; *p; p++) ;
for (p--; *p != '/' && p >= currentFileName; p--) ;
if (*p == '/') p++; else p = currentFileName;
codeFileRoot = (char *) malloc((unsigned)strlen(p) + 1);
strcpy(codeFileRoot, p);
for (p = codeFileRoot; *p; p++) ;
for (p--; *p != '.'; --p) ;
if (p > codeFileRoot) *p = '\0';
}
if (tflag) {
treeFileName = (char *) malloc((unsigned)strlen(codeFileRoot) + 6);
(void) strcpy(treeFileName, codeFileRoot);
(void) strcat(treeFileName, ".tree");
treeFile = fopen(treeFileName, "w");
if (treeFile == NULL) {
fprintf(stderr, "Can't open the tree file (%s).\n", treeFileName);
exit (1);
}
free(treeFileName);
}
doTree("parsing", treeFile, Root);
finishedPass = 1;
checkCompletion();
TRACE0(passes, 1, "Removing sugar.");
removeSugar(&Root);
doTree("removing sugar", treeFile, Root);
CheckForErrors();
finishedPass = 2;
checkCompletion();
TRACE0(passes, 1, "Resolving symbols.");
processSymbols(Root);
doTree("processing symbols", treeFile, Root);
CheckForErrors();
finishedPass = 3;
checkCompletion();
TRACE0(passes, 1, "Doing imports.");
doImports(Root);
doTree("doing imports", treeFile, Root);
CheckForErrors();
finishedPass = 4;
checkCompletion();
initializeOwnStuff();
TRACE0(passes, 1, "Doing manifests.");
doKnowManifests(Root);
doTree("doing manifests", treeFile, Root);
CheckForErrors();
finishedPass = 5;
checkCompletion();
TRACE0(passes, 1, "Assigning types.");
newAssignTypes(Root, 9999);
doTree("assigning types", treeFile, Root);
CheckForErrors();
finishedPass = 6;
checkCompletion();
if (! loadedDummyBuiltins) {
TRACE0(passes, 1, "Checking the types.");
typeCheck(Root);
doTree("checking types", treeFile, Root);
CheckForErrors();
}
finishedPass = 7;
checkCompletion();
if (cflag && !bflag) return;
/*
* Inlineable routines and signal and continue detection.
*/
TRACE0(passes, 1, "Inline detection.");
detectInlines(Root);
doTree("inline detection", treeFile, Root);
CheckForErrors();
finishedPass = 8;
checkCompletion();
doSymbolGraph(Root);
if (OPTION(knowct, 1) && !loadedDummyBuiltins) {
TRACE0(passes, 1, "Figuring out Concrete Types.");
doKnowCTs(Root);
doTree("figuring concrete types", treeFile, Root);
CheckForErrors();
finishedPass = 9;
checkCompletion();
}
if (OPTION(locals, 1) && !loadedDummyBuiltins) {
TRACE0(passes, 1, "Figuring out Locals.");
doKnowLocals(Root);
doTree("figuring locals", treeFile, Root);
CheckForErrors();
finishedPass = 10;
checkCompletion();
}
TRACE0(passes, 1, "Doing exports.");
doExports(Root);
doTree("doing exports", treeFile, Root);
CheckForErrors();
finishedPass = 11;
checkCompletion();
if (cflag) return;
TRACE0(passes, 1, "Code generation.");
codeFileName = (char *) malloc((unsigned)strlen(codeFileRoot) + 16);
generateCode(Root);
doTree("code generation", treeFile, Root);
free(codeFileName);
if (codeFile != NULL && fclose(codeFile) == EOF) assert(FALSE);
CheckForErrors();
finishedPass = 12;
checkCompletion();
systemBuffer = (char **) malloc((unsigned) 6 * sizeof(char *));
systemBuffer[1] = (char *)malloc((unsigned) strlen(codeFileRoot) + 10);
systemBuffer[5] = (char *)malloc((unsigned) strlen(codeFileRoot) + 10);
systemBuffer[0] = "as";
systemBuffer[2] = "-o";
systemBuffer[3] = (char *) NULL;
systemBuffer[4] = (char *) NULL;
TRACE0(passes, 1, "Assembling.");
assert(nextObjectNumber == nextDotsFile);
for (i = 0; i < nextDotsFile; i++) {
TRACE5(doto, 3,
"i=%d alreadyGenerated=%s codeFileNumber=%d codeOID=0x%08x createdOID=0x%08x",
i, dotsFiles[i].alreadyGenerated ? "true" : "false",
dotsFiles[i].codeFileNumber, dotsFiles[i].codeOID,
dotsFiles[i].createdOID);
sprintf(systemBuffer[5], "%s.%d.o", codeFileRoot, i);
realDotoFileName = makeOIDDotoFileName(dotsFiles[i].codeOID);
if (! dotsFiles[i].alreadyGenerated) {
sprintf(systemBuffer[1], "%s.%d.s", codeFileRoot, i);
systemBuffer[3] = realDotoFileName;
systemResult =
callsys("/bin/as", systemBuffer, (char *)NULL, (char *)NULL);
if (systemResult != 0) {
ErrorMessage(Root, "As error");
} else {
if (dotsFiles[i].createdOID != 0) {
/* we need to link the other name to the original name */
createdDotoFileName = makeOIDDotoFileName(dotsFiles[i].createdOID);
myLink(realDotoFileName, createdDotoFileName, FALSE, Root);
free(createdDotoFileName);
}
#ifdef sun
/* we need to fix the header */
{
int inf;
struct exec header;
inf = open(realDotoFileName, O_RDWR, 0);
assert(inf != NULL);
if (read(inf, &header, sizeof(header)) != sizeof(header))
assert(FALSE);
#define CHECK(S) if (!(S)) assert(FALSE);
CHECK(header.a_text != 0);
CHECK(header.a_data == 0);
CHECK(header.a_drsize == 0);
header.a_data = header.a_text;
header.a_drsize = header.a_trsize;
header.a_text = 0;
header.a_trsize = 0;
if (lseek(inf, 0L, 0) < 0) assert(FALSE);
if (write(inf, &header, sizeof(header)) != sizeof(header)) assert(FALSE);
(void) close(inf);
}
#endif
}
}
if (zflag) myLink(realDotoFileName, systemBuffer[5], TRUE, Root);
free(realDotoFileName);
}
CheckForErrors();
if (!zflag) {
for (i = 0; i < nextObjectNumber; i++) {
if (dotsFiles[i].alreadyGenerated) continue;
sprintf(systemBuffer[1], "%s.%d.s", codeFileRoot, i);
systemResult = unlink(systemBuffer[1]);
if (systemResult < 0) {
ErrorMessage(Root, "Cannot unlink %s: %s", systemBuffer[1],
errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
}
}
}
sprintf(systemBuffer[1], "%s.g", codeFileRoot);
if ((dotgFile = fopen(systemBuffer[1], "w")) == NULL) {
ErrorMessage(Root, "Cannot create %s", systemBuffer[1]);
} else {
struct stat st;
DBM *dotgDBM;
char dotgDBMName[1024];
datum keydatum, valuedatum;
fprintf(dotgFile, "#!%sbin/re\n", emDirectory);
fprintf(dotgFile, "0x%08xzzzzzz\n", dotsFiles[0].codeOID);
fstat(fileno(dotgFile), &st);
fchmod(fileno(dotgFile), st.st_mode | 0111);
fclose(dotgFile);
sprintf(dotgDBMName, "%s/DB/dotgdb", emdbDirectory);
if ((dotgDBM = dbm_open(dotgDBMName, O_RDWR | O_CREAT, 0777)) <= 0) {
ErrorMessage(Root, "Can't open the data base file %s\n", dotgDBMName);
} else {
if (getwd(dotgDBMName) == 0) {
ErrorMessage(Root, "Can't determine the current directory: %s\n",
dotgDBMName);
} else {
keydatum.dptr = dotgDBMName;
keydatum.dsize = strlen(dotgDBMName) + 1;
valuedatum.dptr = "x";
valuedatum.dsize = 2;
if (dbm_store(dotgDBM, keydatum, valuedatum, DBM_REPLACE) < 0) {
ErrorMessage(Root, "Can't write to .g filename database");
}
}
dbm_close(dotgDBM);
}
}
finishedPass = 13;
checkCompletion();
TRACE0(passes, 1, "Invoking the kernel.");
execvec = (char **) malloc(10 * sizeof(char *));
execvec[0] = "runec";
i = 1;
if (vflag) execvec[i++] = "-v";
if (iflag) execvec[i++] = "-i";
if (mflag) {
execvec[i++] = "-m";
execvec[i++] = mdata;
}
execvec[i++] = systemBuffer[1];
execvec[i] = (char *) 0;
sprintf(binpath, "%s/bin/runec", emDirectory);
execv(binpath, execvec);
assert(FALSE);
CheckForErrors();
finishedPass = 14;
checkCompletion();
free(systemBuffer[1]);
free(systemBuffer[7]);
free(codeFileRoot);
}
void nextCodeFileName()
{
if (codeFile != NULL) {
if (fclose(codeFile) == EOF) assert(FALSE);
codeFile = NULL;
}
sprintf(codeFileName, "%s.%d.s", codeFileRoot, nextObjectNumber);
}
extern Boolean doGenerateCode, environmentWasImported();
/*
* This one either:
* 1. returns TRUE
* 2. returns FALSE,opens the codeFile for .s writing
* In either case it fills in the dotsFiles structure so that we can do the
* right thing later.
*/
Boolean easyGenerateObject(obj, fCodeOID, fOID)
NodePtr obj;
OID fCodeOID, fOID;
{
char *realDotoFileName;
static Boolean theAnswer;
struct stat statbuf;
int sysresult;
if (doGenerateCode) return(theAnswer);
if (nextDotsFile >= MAXDOTSFILES) {
fprintf(stderr, "Too many output code files.\n");
}
assert(fCodeOID != 0);
if (bflag) {
if (environmentWasImported(fCodeOID)) {
theAnswer = TRUE;
} else {
theAnswer = FALSE;
}
} else {
realDotoFileName = makeOIDDotoFileName(fCodeOID);
theAnswer = TRUE;
sysresult = stat(realDotoFileName, &statbuf);
if (sysresult < 0) {
if (errno == ENOENT) theAnswer = FALSE;
else {
ErrorMessage(obj, "Cannot stat %s: %s", realDotoFileName,
errno < sys_nerr ? sys_errlist[errno] : "unknown reason");
}
}
free(realDotoFileName);
}
dotsFiles[nextDotsFile].alreadyGenerated = theAnswer;
dotsFiles[nextDotsFile].codeFileNumber = nextObjectNumber;
dotsFiles[nextDotsFile].codeOID = fCodeOID;
dotsFiles[nextDotsFile].createdOID = fOID;
TRACE4(doto, 1,
"\"%s\" %s code=0x%08x created=0x%08x",
obj && (obj->tag == P_OBLIT || obj->tag == P_ATLIT) ?
ST_SymbolName(obj->b.oblit.name->b.symdef.symbol) : "<?>",
dotsFiles[nextDotsFile].alreadyGenerated ? "AG" : "!AG",
dotsFiles[nextDotsFile].codeOID,
dotsFiles[nextDotsFile].createdOID);
nextDotsFile++;
nextCodeFileName();
if (! theAnswer) {
codeFile = fopen(codeFileName, "w");
if (codeFile == NULL) {
fprintf(stderr, "Can't open the code file (%s).\n", codeFileName);
exit (1);
}
}
return(theAnswer);
}
extern void init_Sugar();
extern void initializebuildATs();
extern void initializeGenerate();
extern void initializeAllocate();
extern void initializeSymbols();
extern void initializeSymbolTable();
extern void initializeEnvironment();
extern void initializeManifest();
extern void initializeTrace();
extern void initializeOption();
extern void initializeGraphs();
extern void initializeKnowCT();
extern void initializeKnowManifest();
extern void initializeKnowLocal();
extern void Scanner_Initialize();
extern void initializeNodes();
void initialize()
{
initializeDataBaseFiles();
initializeNodes();
ON_initialize();
init_Conforms();
init_Sugar();
initializebuildATs();
initializeAllocate();
initializeGenerate();
initializeSymbols();
initializeSymbolTable();
initializeEnvironment();
initializeManifest();
initializeRegisters();
initializeTrace();
initializeOption();
initializeGraphs();
initializeKnowCT();
initializeKnowManifest();
initializeKnowLocal();
Scanner_Initialize();
}
void Finalize()
{
ON_finalize();
}